<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="author" content="Austin Delamar">
    <meta name="keywords" content="java,hash,encrypt,pbdkf2,sha,sha256,sha512,bcrypt,scrypt,password,software,library">
    <meta name="description" content="Password hashing utility in Java. It salts automatically and has a pepper option. Supports PBKDF2 SHA1, SHA256, SHA512, and BCRYPT." />
    <meta name="robots" content="all">

    <!-- Open Graph data -->
    <meta property="og:url" content="https://amdelamar.com/jhash/">
    <meta property="og:type" content="website">
    <meta property="og:locale" content="en_US">
    <meta property="og:title" content="Jhash">
    <meta property="og:image" content="https://amdelamar.com/jhash/img/blue-key-200x200.png">
    <meta property="og:description" content="Password hashing utility in Java. It salts automatically and has a pepper option. Supports PBKDF2 SHA1, SHA256, SHA512, and BCRYPT.">

    <!-- Twitter Card data -->
    <meta name="twitter:card" content="summary">
    <meta name="twitter:site" content="https://amdelamar.com/jhash/">
    <meta name="twitter:creator" content="amdelamar">
    <meta name="twitter:title" content="Jhash">
    <meta name="twitter:description" content="Password hashing utility in Java. It salts automatically and has a pepper option. Supports PBKDF2 SHA1, SHA256, SHA512, and BCRYPT.">
    <meta name="twitter:image" content="https://amdelamar.com/jhash/img/blue-key-200x200.png">

    <!-- Schema.org markup for Google+ -->
    <meta itemprop="name" content="Jhash">
    <meta itemprop="description" content="Password hashing utility in Java. It salts automatically and has a pepper option. Supports PBKDF2 SHA1, SHA256, SHA512, and BCRYPT.">
    <meta itemprop="image" content="https://amdelamar.com/jhash/img/blue-key-200x200.png">

    <link rel="icon" type="image/x-icon" href="img/blue-key-32x32.png">
    <link rel="stylesheet" href="https://amdelamar.com/osseous/3.0.0/osseous.min.css">
    <link rel="stylesheet" href="vendor/icomoon/icomoon.css">
    <link rel="stylesheet" href="vendor/highlight/default.css">
    <link rel="stylesheet" href="https://amdelamar.com/css/style.min.css">
    <title>Jhash - Password hashing utility in Java</title>
</head>
<body>

  <!-- Landing logo, title, and subtitle. -->
  <header class="row padding-top-large margin-top-large">
      <div class="container text-center">
          <div class="twelve columns">
              <img class="round" src="img/blue-key-200x200.png" width="200" height="200" alt="Banner" title="Photo Credit: Typography Images at Pixabay.com" />
          </div>
          <div class="twelve columns">
              <h1 class="text-uppercase text-thinner text-wide">Jhash</h1>
              <p>Password hashing utility in Java. Supports PBKDF2 hmac SHA1/SHA256/SHA512, BCRYPT, and SCRYPT. It salts automatically and has a pepper option.</p>
              <p>
                  <a class="button button-primary" target="_blank" href="https://github.com/amdelamar/jhash/releases"><span class="icon-embed text-medium margin-right"></span>Download</a>
                  <a class="button button-secondary" href="https://github.com/amdelamar/jhash/"><span class="icon-github text-medium margin-right"></span>View on GitHub</a>
                  <a class="button" href="https://github.com/amdelamar/jhash/issues"><span class="icon-bug text-medium margin-right"></span>Report Issue</a>
              </p>
              <code>v2.2.0</code> - 21 Sep 2020 - <code>47KB</code>
          </div>
      </div>
  </header>

  <!-- Main Content -->
  <article class="container">

            <!-- Description Section -->
            <div id="description" class="row section">
            <h3>Download</h3>
            <p>
                Add to your project using Maven, Gradle, or download the jar directly.
            </p>

            <p>Maven:</p>
            <pre><code class="xml">&lt;dependency&gt;
    &lt;groupId&gt;com.amdelamar&lt;/groupId&gt;
    &lt;artifactId&gt;jhash&lt;/artifactId&gt;
    &lt;version&gt;2.2.0&lt;/version&gt;
&lt;/dependency&gt;</code></pre>

            <p>Gradle:</p>
            <pre><code class="groovy">dependencies {
    compile 'com.amdelamar:jhash:2.2.0'
}
</code></pre>

                <p>SBT:</p>
                <pre><code class="scala">libraryDependencies ++= Seq(
    "com.amdelamar" % "jhash" % "2.2.0"
)
</code></pre>

            <p>Or Download the <a href="https://github.com/amdelamar/jhash/releases">latest release</a>.

			<br>
			<h3>Usage</h3>

            <pre><code class="java">import com.amdelamar.jhash.Hash;

char[] password = "Hello World!".toCharArray();

// salt + hash a password. (pbkdf2 hmac sha1)
String hash = Hash.password(password).create();
// Example: pbkdf2sha1:64000:18:24:n:LZXY631xphycV5kaJ2WY0RRDqSfwiZ6L:uOw06jt6FvimXSxEJipYYHsQ

// Save the enitre string somewhere safe...

// Verify Login
if(Hash.password(password).verify(correctHash)) {
    // Passwords match. Login successful!
}</code></pre>

		<p>More Options:</p>

<pre><code class="java">// pbkdf2 hmac sha512 + salt
String hash = Hash.password(password).algorithm(Type.PBKDF2_SHA512).create();
// Returns: pbkdf2sha512:64000:18:24:n:EbroMczUKuBRx5sy+hgFQyHmqk2iNtt5:Ml8pGxc3pYoh1z5fkk5rfjM9

// pbkdf2 hmac sha256 + salt + pepper
String hash = Hash.password(password).pepper(pepper).algorithm(Type.PBKDF2_SHA256).create();
// Returns: pbkdf2sha256:64000:18:24:y:J84o+zGuJebtj99FiAMk9pminEBmoEIm:4hoNRxgrn79lxujYIrNUXQd1

// pbkdf2 hmac sha512 + salt + pepper + higher salt length
String hash = Hash.password(password).pepper(pepper).algorithm(Type.PBKDF2_SHA512).saltLength(36).create();
// Returns: pbkdf2sha512:64000:18:36:y:v+tqRNA5B4cAxbZ4aUId/hvrR+FlS1d8:/R851fqvd7HItsSr0vJEupBf

// bcrypt + salt
String hash = Hash.password(password).algorithm(Type.BCRYPT).create();
// Example: bcrypt:13:66:16:n::$2a$10$YQ9urAM3RKuDtl1XaF99HrdpoIlB6ZhfaGR1T4yS4jlfMSPyeXehE.0Dway

// bcrypt + salt + pepper
String hash = Hash.password(password).pepper(pepper).algorithm(Type.BCRYPT).create();
// Example: bcrypt:13:66:16:y::$2a$10$UlxpnyYwYmmlLgl7YVGonN9H74ffEttiD1O2uMy8q5Y7YgJc8.YsRa3yOM6

// scrypt + salt
String hash = Hash.password(password).algorithm(Type.SCRYPT).create();
// Example: scrypt:16384:80:24:n::$s0$e0801$+nNFxTV9IHyN0cPKn/ORDA==$uPrBpPBQm7GgX+Vcc/8zuFNJZ+8XqDMylpLrOjv6X8w=

// scrypt + salt + pepper
String hash = Hash.password(password).pepper(pepper).algorithm(Type.SCRYPT).create();
// Example: scrypt:16384:80:24:y::$s0$e0801$iHSTF05OtGCb3BiaFTZ3BA==$QANWx2qBzMzONIQEXUJTWnNX+3wynikSkGJdO9QvOx8=

// scrypt + salt + pepper + higher complexity factor
String hash = Hash.password(password).pepper(pepper).algorithm(Type.SCRYPT).factor(1048576).create();
// Example: scrypt:16384:80:24:y::$s0$e0801$iHSTF05OtGCb3BiaFTZ3BA==$QANWx2qBzMzONIQEXUJTWnNX+3wynikSkGJdO9QvOx8=</code></pre>

	    <p>Now verify the passwords match. Even if you use a stronger algorithm, longer salt length, or increase the complexity factor,
		    you don't need to provide that information when you <code>verify()</code> because the hash output has
		    those values already. But if you used a pepper, you need to provide that when verifying.</p>

		<pre><code class="java">// Verify Login
if(Hash.password(password).verify(correctHash)) {
    // Passwords match. Login successful!
}

// Provide the pepper if you used one.
// (This is because the pepper isn't stored with the hash!)
if(Hash.password(password).pepper(pepper).verify(correctHash)) {
    // Passwords match. Login successful!
}
</code></pre>


            <br />
            <h3>Hash Format</h3>

	    <p>The hash format is seven fields separated by the colon (':') character.</p>

            <code>algorithm:factor:hashLength:saltLength:pepper:salt:hash</code>

	    <p>Examples:</p>

            <pre><code>pbkdf2sha1:64000:18:24:n:LZXY631xphycV5kaJ2WY0RRDqSfwiZ6L:uOw06jt6FvimXSxEJipYYHsQ
pbkdf2sha256:64000:18:24:n:ZhxPG2klUysxywJ7NIAhFNTtEKa1U2yu:6oeoGuoQAOIKsztgIgPHTC4/
pbkdf2sha256:64000:18:24:y:8MD0yEl5DKz+8Av2L8985h63BhvVppYU:osTwsDh2qo/wgE6g0BrjdeFt
pbkdf2sha512:64000:18:24:n:EbroMczUKuBRx5sy+hgFQyHmqk2iNtt5:Ml8pGxc3pYoh1z5fkk5rfjM9
pbkdf2sha512:64000:18:24:y:v+tqRNA5B4cAxbZ4aUId/hvrR+FlS1d8:/R851fqvd7HItsSr0vJEupBf
bcrypt:13:66:16:n::$2a$10$YQ9urAM3RKuDtl1XaF99HrdpoIlB6ZhfaGR1T4yS4jlfMSPyeXehE.0Dway
bcrypt:13:66:16:y::$2a$10$sdreyOHQW0XAGw.LMXbPyayMMGlMuU69htdw8KXjzk5xOrVTFj2aYLxre7y
scrypt:131072:80:24:n::$s0$e0801$Evw8WPqcEUy1n3PhZcP9pg==$lRbNPFoOdoBMFT0XUcZUPvIxCY8w+9DkUklXIqCOHks=
scrypt:131072:80:24:y::$s0$e0801$mzUhOD/ns1JCnwhsYPvIkg==$OlipMfOQJkCm62kY1m79AgIsfPzmIDdgz/fl/68EQ+Y=</code></pre>

            <ul>
            <li><code>algorithm</code> is the name of the cryptographic hash function.</li>
            <li><code>factor</code> is the complexity of the algorithm. PBKDF2 number of iterations (64000), BCRYPT number of logrounds (2<sup>13</sup>), SCRYPT cpu/mem cost (131072).</li>
            <li><code>hashLength</code> the byte length of the <code>hash</code>.</li>
            <li><code>saltLength</code> the byte length of the <code>salt</code>.</li>
            <li><code>pepper</code> is an indicator that a pepper was used ('y' or 'n').</li>
            <li><code>salt</code> is the salt. (Note: BCRYPT and SCRYPT salt is embeded in the hash).</li>
            <li><code>hash</code> is the raw password hash.</li>
            </ul>

            <br />
            <h3>Options and Considerations</h3>
            <h5>PBKDF2 Options</h5>
            <p>You have three options with PBKDF2 hmac: SHA1, SHA256, or SHA512. Test each before you try them, because not all JVM's support the newer hashing methods. Java 8 added support for PBKDF2 with SHA512 in 2014.</p>
            <p>The default iterations = 64,000 but feel free to increase up to 200,000 depending on your server and cpu cost you want. Run some preliminary tests to find out if hashes are too quick. You'll want <strong>at least 0.5 seconds</strong> per hash and no faster.</p>
            <h5>BCrypt Options</h5>
            <p>The default logrounds = 13 but feel free to increase up to 20 depending on the cpu cost you want. Again, run some preliminary tests to find out if hashes are too quick. Here is a quick estimate:</p>
            <ul>
            <li>12 = About ~250 ms each hash.</li>
            <li>13 = About ~500 ms each hash. <span class="icon-star"></span> default</li>
            <li>14 = About ~1 second each hash.</li>
            <li>15 = About ~2 seconds each hash.</li>
            <li>16 = About ~4.5 seconds each hash.</li>
            </ul>
            <p>Also note that BCrypt has a password limit of 72 characters (18 32-bit words). Be sure to truncate before hashing. Its a limitiation of the Blowfish cipher. BCrypt has a default salt length of 16 to remain compatible with the standard formula, but you can increase this if you wish.</p>
            <h5>SCrypt Options</h5>
            <p>The default cost = 131072 (2<sup>17</sup>) but you can increase this too. Again, run some preliminary tests to find out if the hashes are computed too quickly. Here is a quick estimate:</p>
            <ul>
            <li>16384  (2<sup>15</sup>) = About ~100 ms each hash.</li>
            <li>131072 (2<sup>17</sup>) = About ~800 ms each hash <span class="icon-star"></span> default</li>
            <li>262144  (2<sup>18</sup>) = About ~2 seconds each hash.</li>
            <li>1048576 (2<sup>20</sup>) = About ~5 seconds each hash.</li>
            </ul>

            <br />
            <h3>Details</h3>
            <p>
            By default, if you just call <code>Hash.password(pwd).create()</code> it uses PBKDF2 hmac SHA1 with 24 bytes (192 bits) of securely random salt and outputs 18 bytes (144 bits). 144 bits was chosen because it is (1) Less than SHA1's 160-bit output (to avoid unnecessary PBKDF2 overhead), and (2) A multiple of 6 bits, so that the base64 encoding is optimal. PBKDF2 hmac SHA1 was chosen for the default mainly for the most compatibility across Java implementations. Although SHA1 has been cryptographically broken as a collision-resistant function, it is still perfectly safe for password storage with PBKDF2. Its my recommendation though to use algorithms like BCRYPT and SCRYPT. As they are 'memory hard', meaning that they don't just need a lot of CPU power to compute, they also require a lot of memory (unlike PBKDF2). This makes them better against brute-force attacks.
            </p>

            <br />
            <h3>Credit</h3>
            <p>
            A project by <a href="https://github.com/amdelamar">Austin Delamar</a> based off of <a href="https://github.com/defuse/password-hashing">Talor Hornby</a>, <a href="https://github.com/jeremyh/jBCrypt">Damien Miller</a>, and <a href="https://github.com/wg/scrypt">Will Grozer</a>'s work and other <a href="https://github.com/amdelamar/jhash/graphs/contributors">contributors</a>.<br>
            <br>
            If you'd like to contribute, feel free to fork and make changes, then open a pull request to <code>master</code> branch.
            </p>
            <p>Looking for version 1.x? Documentation is <a href="/jhash/v1.1.0/">over here</a>.</p>

            <br />
            <h3>License</h3>

            <p>Jhash is licensed as <a href="https://github.com/amdelamar/jhash/blob/master/LICENSE">MIT</a>
            <br><br>
            PBKDF2 is licensed as <a href="https://github.com/amdelamar/jhash/blob/master/LICENSE">BSD-2-Clause</a>
            <br><br>
            BCRYPT is licensed as <a href="https://github.com/amdelamar/jhash/blob/master/LICENSE">ISC</a>
            <br><br>
            SCRYPT is licensed as <a href="https://github.com/amdelamar/jhash/blob/master/LICENSE">Apache-2.0</a></p>
        </div>

</article>

<!-- Footer at bottom -->
<footer class="row section text-center">
    <p><small><em>&#169; <a href="https://amdelamar.com">AustinDelamar</a> - 2017-2018</em></small></p>
    <a class="button button-primary float-right margin-right-large" title="Back to top" href="#">Back to Top</a>
</footer>

<!-- Highlightjs for color coding -->
<script src="vendor/highlight/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

</body>
</html>
